#include <Arduino.h>
#include <AccelStepper.h>
#include <ESP8266WiFi.h>
#include <Ticker.h>
#include <PubSubClient.h>

#define FULLSTEP 4
#define ROUND 2038
#define MAX_SPEED 500.0
#define SPEED 200
#define ACCLERATION 150.0
#define IN1 14
#define IN2 13
#define IN3 12
#define IN4 15
#define BUTTON 0
#define BUILTIN_LED 2

#define WIFI_SSID "kexue_R"
#define WIFI_PASSWORD "kexue666"

#define MQTT_SUB "test/in"

// MQTT服务端连接用户名密码
const char *mqttUserName = "mqtt";
const char *mqttPassword = "mqtt";
const char *mqttServer = "192.168.123.4";
static int mqttPort = 1883;

AccelStepper myStepper(FULLSTEP, IN1, IN2, IN3, IN4);

WiFiClient wifiClient;
WiFiEventHandler wifiConnectHandler;
WiFiEventHandler wifiDisconnectHandler;
Ticker wifiReconnectTimer;

PubSubClient mqttClient(wifiClient);

static int mqtt_time = 0;

// 连接Wi-Fi
void connectToWifi()
{
  Serial.println("Connecting to Wi-Fi...");
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}

// MQTT回调
void callback(char *topic, byte *payload, unsigned int length)
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++)
  {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  if ((char)payload[0] != '0')
  {
    digitalWrite(BUILTIN_LED, LOW);
    myStepper.runToNewPosition((int(payload[0]) - 48) * ROUND);
    digitalWrite(BUILTIN_LED, HIGH);
  }
}

// 连接到Wi-Fi
void onWifiConnect(const WiFiEventStationModeGotIP &event)
{
  Serial.println("Connected to Wi-Fi.");
}

// Wi-Fi断开连接
void onWifiDisconnect(const WiFiEventStationModeDisconnected &event)
{
  Serial.println("Disconnected from Wi-Fi.");
  wifiReconnectTimer.once(2, connectToWifi);
}

void button_press()
{
  myStepper.moveTo(ROUND);

  if (mqtt_time == 0)
  {
    mqttClient.publish("test/out", "Button pressed, moving to 1L");
    Serial.println("Button pressed, moving to 1L");
    mqtt_time = 1;
  }
}

// 主函数
void setup()
{
  Serial.println();
  Serial.println();
  Serial.begin(115200);

  // 按钮
  pinMode(INPUT_PULLUP, BUTTON);

  // 灯
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  // Wi-Fi连接/断开动作
  wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect);
  wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);

  // 连接Wi-Fi
  connectToWifi();

  // MQTT
  mqttClient.setServer(mqttServer, mqttPort);
  mqttClient.setCallback(callback);

  // 电机
  myStepper.setMaxSpeed(MAX_SPEED);
  myStepper.setAcceleration(ACCLERATION);
  myStepper.setSpeed(SPEED);
  myStepper.setCurrentPosition(ROUND);
}

void reconnect()
{
  while (!mqttClient.connected())
  {
    Serial.print("Tring to connect MQTT server...");
    // client ID
    String clientId = "ESP8266";
    // 连接
    if (mqttClient.connect(clientId.c_str(), mqttUserName, mqttPassword))
    {
      Serial.println("connected");
      // 上线通知
      mqttClient.publish("test/out", "Online");
      // 订阅
      mqttClient.subscribe("test/in");
    }
    else
    {
      Serial.print("failed, rc=");
      Serial.print(mqttClient.state());
      Serial.println(" try again in 5 seconds");

      delay(5000);
    }
  }
}

// 主循环
void loop()
{
  // 按钮检测
  if (digitalRead(0) == 0)
  {
    button_press();
  }
  else
  {
    mqtt_time = 0;
  }

  if (!mqttClient.connected())
  {
    reconnect();
  }

  mqttClient.loop();

  // 电机运行
  myStepper.run();
}